package com.yzr.common.thread.pool;

import java.util.concurrent.Executors;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 线程池不允许使用Executors去创建，而是通过ThreadPoolExecutor的方式，这样
 * 的处理方式让写的同学更加明确线程池的运行规则，规避资源耗尽的风险。
 * 说明：Executors返回的线程池对象的弊端如下：
 * 1）FixedThreadPool和SingleThreadPool:
 * 允许的请求队列长度为Integer.MAX_VALUE，可能会堆积大量的请求，从而导致OOM。
 * 2）CachedThreadPool和ScheduledThreadPool:
 * 允许的创建线程数量为Integer.MAX_VALUE，可能会创建大量的线程，从而导致OOM。
 * <p>
 * 假设银行现有5个窗口，等候区有3个位子，2个窗口办理业务，当2个窗口都在办理业务，等候区的三个位子也满了
 * 这时再进来一个人，就会再开启一个窗口，这时又进来了两个人办理业务，这时五个窗口全部开启，
 * 当再进来一个人时？
 * 线程池的4种拒绝策略：
 * 1.new ThreadPoolExecutor.AbortPolicy()  // 当在进来一个人时，不办理，给他打一顿（抛出异常）
 * 2.new ThreadPoolExecutor.CallerRunsPolicy() // 哪里来的回哪里去，从main线程进来的，会再交由main线程去执行
 * 3.new ThreadPoolExecutor.DiscardPolicy() // 队列满了，丢掉任务，不会抛出异常
 * 4.new ThreadPoolExecutor.DiscardOldestPolicy() // 队列满了，尝试去和最早的线程竞争，也不会抛出异常。
 */
public class ThreadPoolDemo {

    public static void main(String[] args) {
        // 最大线程池，如何设置？
        // 1.cpu密集型，cpu几核？就是几，可以保持cpu的效率最高
        // 2.io密集型，> 判断你程序中十分消耗io的线程
        // 程序   如15个大型任务  io 十分消耗资源

        // 获取cpu的核数
        int cpuCoreNumber = Runtime.getRuntime().availableProcessors();
        System.out.println(cpuCoreNumber);
        ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(2,
                cpuCoreNumber,
                3,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<>(3),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
        try {
            for (int i = 1; i <= 7; i++) {
                threadPoolExecutor.execute(() -> {
                    System.out.println(Thread.currentThread().getName() + "执行");
                });
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            threadPoolExecutor.shutdown();
        }

    }

}
